AWS Secrets Managerで RDSのパスワードローテーションしてみる in 2022

AWS Secrets Managerで RDSのパスワードローテーションしてみる in 2022

Clock Icon2022.01.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、AWS 事業本部コンサルティング部のたかくに(@takakuni_)です。

今回はタイトルの通り、AWS Secrets Manager で RDS のパスワードローテーションをしてみようと思います。

弊社ブログ内でいくつが既に紹介されていますが、Secrets Manager が VPC エンドポイントをサポートしていたためアップデート記事となります。

年初めに、タイトルに「in 2022」をつけて大丈夫か内心ソワソワしています...

2022 年 12 月 23 日追記

年の終わりにまさかのアップデートがありました。

Amazon RDS と Secrets Manager が直接統合され、より簡単にパスワードローテーションできるようになりました。詳しくは以下をご覧ください!

https://hatenablog-parts.com/embed?url=https://dev.classmethod.jp/articles/aws-rds-integration-aws-secrets-manager/

公式ドキュメント

弊社ブログ

構成図

ポイントは以下の通りです。

  1. セッションマネージャー使用用途で ssm、ec2message、ssmmessages の VPC エンドポイントを作成します。Secrets Manager とは直接的に関係はありません。
  2. Lambda から Secrets の取得用途で、 secretsmanager の VPC エンドポイントを作成します。
  3. 接続テスト用 EC2 インスタンスには、既に MySQL クライアントがインストールされています。
  4. 今回はテスト用のため Lambda 関数は、RDS と同一サブネットに配置していますが、同一 VPC 内であれば別サブネットに配置して問題ありません
  5. ap-northeast-1c に配置したサブネットは、サブネットグループを作成するために使用するサブネットです。
  6. VPC エンドポイントの設定が完了後、チュートリアル: AWS データベースのシークレットをローテーションするの手順を踏んでいきます。(必要に応じて読み替えを行います。)

事前準備 その 1:セキュリティグループの作成

使用するセキュリティグループは以下になります。

  • テスト用 EC2 インスタンスのセキュリティグループ
  • Lambda のセキュリティグループ
  • RDS のセキュリティグループ
  • VPC エンドポイント(ssm, ssmmessages, ec2messages)のセキュリティグループ
  • VPC エンドポイント(secretsmanager)のセキュリティグループ

セキュリティグループのルール設定

各セキュリティグループの詳細です。

テスト用 EC2 インスタンスのセキュリティグループ

  • インバウンドルール:無し(セッションマネージャーで接続)
  • アウトバウンドルール:フルオープン

Lambda のセキュリティグループ

  • インバウンドルール:無し
  • アウトバウンドルール:フルオープン
参考:アウトバウンドのセキュアパターン
CIDR/SG ポート 用途
RDS の SG 3306 パスワード変更で接続するため
VPC エンドポイント(secretsmanager)の SG 443 パスワード取得で接続するため

RDS のセキュリティグループ

インバウンドルールは以下の通り

CIDR/SG ポート 用途
Lambda の SG 3306 パスワード変更で接続するため
EC2 3306 テストで接続するため
  • アウトバウンドルール:フルオープン

VPC エンドポイント(ssm, ssmmessages, ec2messages)のセキュリティグループ

インバウンドルールは以下の通り

CIDR/SG ポート 用途
テスト接続用 EC2 の SG 443 セッションマネージャーで接続するため
  • アウトバウンドルール:無し

VPC エンドポイント(secretsmanager)のセキュリティグループ

インバウンドルールは以下の通り

CIDR/SG ポート 用途
Lambda の SG 443 パスワード取得で接続するため

加えて、EC2 の環境変数に Secrets Manager の情報(DB のユーザ・パスワード)を登録する方法は、こちらをご参照ください。

  • アウトバウンドルール:無し

事前準備 その 2:VPC エンドポイントの設定

VPC エンドポイントを 4 つ(ssm, ssmmessages, ec2messages, secretsmanager)作成します。

ステップ 1: テスト用 MySQL データベースの設定

検証用の RDS インスタンスを作成します。

RDS の設定値は次の通り設定しました。

設定値
DB インスタンス識別子 MyTestDatabaseInstance
マスターユーザー名 adminuser
マスターパスワード KeyRotatePassword

チュートリアルとの相違点(テスト用 MySQL データベースの設定)

ドキュメントではパブリックアクセスを「Yes」に変更していますが、今回は VPC Endpoint 経由でアクセスするため No のまま設定 しました。

セキュリティグループ設定欄で事前準備した RDS 用セキュリティグループ を設定しました。

ステップ 2: シークレットを作成する

Secrets Manager コンソール画面からシークレットを作成します。

ステップ 1 で指定したユーザー名、パスワード、ローテーション対象の RDS インスタンスを設定します。

「次へ」をクリックすると、シークレット名と説明の設定画面へ遷移します。

シークレットの名前は、チュートリアルの通り「MyTestDatabaseMasterSecret」と設定しました。

「次へ」を選択すると、ローテーション設定に遷移します。

今回は、事前に RDS で設定したパスワードの接続確認を行うため、チュートリアルに従い「自動ローテーション」は無効に設定します

![https://devio2023-media.developers.io/wp-content/uploads/2022/01/1c21c68fbaf1ffb18a8a5df5e69a7a68-640x423.jpg]

作成するシークレットの確認画面へ遷移します。

問題なければ、「保存」でシークレットを作成します。

シークレットが作成されました。

ステップ 3: 最初のシークレットを検証する

接続確認用 EC2 インスタンスから RDS へ接続を行います。シークレットとして登録した後でも問題なく接続できました。

ステップ 4: シークレットのローテーションを設定する

ここからが本題です。

ステップ 2 にて作成したシークレットにローテーション機能を追加します。

Secrets Manager コンソールからステップ 2 にて作成したシークレットを選択し、「ローテーション構成」の変更を行いました。

ローテーション間隔は、1 から 365 日までで選択可能でした。

ローテーション設定を保存すると画面上部のポップアップに「ローテーション用の AWS CloudFormation リソースを作成します。」と表示されました。

内部的に、スタックを作成する仕組みのようです。

ステップ 4 +α: Lambda 関数の VPC 設定を行う

VPC Endpoint へ Lambda 関数が接続できるように「VPC 設定」を変更します。

セキュリティグループを事前準備で作成したLambda 用のセキュリティグループに変更します。

ステップ 5: 成功したローテーションの確認

それでは、パスワードを変更していきましょう。

再び Secrets Manager コンソールへ戻り、シークレットを選択。

「ローテーション構成」から「シークレットをローテーションさせる」を選択します。

シークレットの値が更新されていることが確認できました!

ステップ 5 +α: 接続確認

新しくローテーションを行ったパスワードで MySQL へ接続を行います。

パスワードの文字列の関係で対話式でログインを行いましたが、問題なくログインできました!

もっと知りたい人向け

CloudFormation で設定されるリソースについて

スタックの中身としては、「AWS::Serverless::Function」、「AWS::IAM::Role」、「AWS::Lambda::Permission」を作成しているみたいです。

ソースコードは以下になります。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
    endpoint:
        Type: String
        Description: The Secrets Manager endpoint to use.
    functionName:
        Type: String
        Description: The name of the Lambda function.
    invokingServicePrincipal:
        Type: String
        Description: The service principal for the invoking service.
        Default: "secretsmanager.amazonaws.com"
    vpcSubnetIds:
        Type: CommaDelimitedList
        Description: A comma-separated list of VPC subnet IDs applied to the database network.
        Default: ""
    vpcSecurityGroupIds:
        Type: CommaDelimitedList
        Description: A comma-separated list of security group IDs applied to the database.
        Default: ""
    kmsKeyArn:
        Type: String
        Description: The ARN of the KMS key that Secrets Manager uses to encrypt the secret.
        Default: ""
    excludeCharacters:
        Type: String
        Description: A string of the characters that you don't want in the password.
        Default: "/@\"'\\" # MySQL DB設定時はデフォルト値が設定されていました。

Conditions:
    AddVpcConfig:
        !And
            - !Not [!Equals ["", !Join ["", !Ref vpcSubnetIds]]]
            - !Not [!Equals ["", !Join ["", !Ref vpcSecurityGroupIds]]]
    KmsKeyArnExists:
        !Not [!Equals ["", !Ref kmsKeyArn]]

Resources:
    SecretsManagerRDSMySQLRotationSingleUser:
        Type: AWS::Serverless::Function
        Properties:
            FunctionName:
                Ref: functionName
            Description: Rotates a Secrets Manager secret for Amazon RDS MySQL credentials using the single user rotation strategy.
            Handler: lambda_function.lambda_handler
            Runtime: python3.7
            CodeUri: s3://secrets-manager-rotation-apps-7c4fea7a5d7a5497325114af491e6b58/SecretsManagerRDSMySQLRotationSingleUser/SecretsManagerRDSMySQLRotationSingleUser.zip # AWSさんのURL 既存EC2からはアクセスできませんでした。
            Timeout: 30
            Policies:
            - VPCAccessPolicy: {}
            - AWSSecretsManagerRotationPolicy:
                FunctionName:
                    Ref: functionName
            - !If
                - KmsKeyArnExists
                - Version: '2012-10-17'
                  Statement:
                      - Effect: Allow
                        Action:
                            - kms:Decrypt
                            - kms:DescribeKey
                            - kms:GenerateDataKey
                        Resource: !Ref kmsKeyArn
                - !Ref "AWS::NoValue"
            Environment:
                Variables:
                    SECRETS_MANAGER_ENDPOINT:
                        Ref: endpoint
                    EXCLUDE_CHARACTERS:
                        Ref: excludeCharacters
            VpcConfig:
                !If
                    - AddVpcConfig
                    -
                        SubnetIds: !Ref vpcSubnetIds
                        SecurityGroupIds: !Ref vpcSecurityGroupIds
                    - !Ref "AWS::NoValue"
            Tags:
                SecretsManagerLambda: Rotation

    LambdaPermission:
        Type: 'AWS::Lambda::Permission'
        Properties:
            Action: 'lambda:InvokeFunction'
            FunctionName: !GetAtt SecretsManagerRDSMySQLRotationSingleUser.Arn
            Principal: !Ref invokingServicePrincipal

Outputs:
    RotationLambdaARN:
        Description: The ARN of the rotation lambda
        Value: !GetAtt SecretsManagerRDSMySQLRotationSingleUser.Arn

自動作成される Lambda に関して

IAM ロール

Lambda に付与される IAM ロールは、AWS 管理ポリシー「AWSLambdaBasicExecutionRole」、「AWSLambdaVPCAccessExecutionRole」に加えて以下のポリシーがインラインポリシーで定義されていました。

また、Lambda のリソースベースポリシーではSecrets Manager からのみ実行できるように制限されていました。

Secrets Manager で IAM ロールを設定していない(できない)ため、Lambda 側から許可する用途で使用されているのではないかと思います。

VPC 設定

ステップ 4 で自動生成された Lambda の「VPC 設定」の初期状態は以下になります。

ほとんど、マスキングでわかりませんが VPC 設定をまとめると以下になります。

  • マルチ AZ でデプロイされる(RDS 本体のマルチ AZ 設定の有無は関係ない)
  • サブネットは RDS のサブネットグループで選択したサブネットで作成される
  • セキュリティグループは、RDS にアタッチされたセキュリティグループと同じセキュリティグループがアタッチされている

まとめ

個人的に、簡単にローテーションを組むことができて画期的な機能だと思いました。

今回、記事としてはネットワーク経路をよりセキュアに変更した記事でしたが、「運用面も考慮して実装したい!」という方は、新サービス「AWS Secrets Manager」をチュートリアル 2 種(基本設定、RDS ローテーション)で基礎から学ぶ 【運用上を気をつけておくべきポイント 3 点】も合わせてご覧いただけますと幸いです。

以上、AWS 事業本部コンサルティング部のたかくに(@takakuni_)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.